package com.ikas.ai.server.module.risk.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ikas.ai.server.error.BusinessException;
import com.ikas.ai.server.module.appraise.dao.AppraiseSceneResultDAO;
import com.ikas.ai.server.module.appraise.enums.ScoreLevelEnum;
import com.ikas.ai.server.module.appraise.model.AppraiseSceneResult;
import com.ikas.ai.server.module.appraise.model.AppraiseSceneResultDetail;
import com.ikas.ai.server.module.appraise.service.AppraiseSceneResultDetailService;
import com.ikas.ai.server.module.risk.dao.RiskReportDAO;
import com.ikas.ai.server.module.risk.model.RiskInspection;
import com.ikas.ai.server.module.risk.model.RiskPolicy;
import com.ikas.ai.server.module.risk.model.RiskReport;
import com.ikas.ai.server.module.risk.model.dto.RiskReportDisposeDto;
import com.ikas.ai.server.module.risk.model.dto.RiskReportQueryDto;
import com.ikas.ai.server.module.risk.model.dto.RiskReportStatisticsDto;
import com.ikas.ai.server.module.risk.model.vo.RiskReportDetailVo;
import com.ikas.ai.server.module.risk.model.vo.RiskReportQueryVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

/**
 * 风险处置报告服务类
 *
 * @author tang.xuandong
 * @version 1.0.0
 * @date 2023/1/31 13:57
 */
@Service
@Transactional
public class RiskReportService extends ServiceImpl<RiskReportDAO, RiskReport> {

    private static final double SUM_SCORE = 100;

    @Autowired
    private RiskReportDAO riskReportDAO;

    @Autowired
    private RiskPolicyService riskPolicyService;

    @Autowired
    private AppraiseSceneResultDAO appraiseSceneResultDAO;

    @Autowired
    private AppraiseSceneResultDetailService appraiseSceneResultDetailService;

    @Autowired
    private RiskInspectionService riskInspectionService;

    /**
     * 分页查询
     *
     * @param req 风险处置报告分页DTO
     * @return List<RiskReportQueryVo>
     */
    public List<RiskReportQueryVo> pageQueryRiskReport(RiskReportQueryDto req) {
        String level = req.getLevel();
        double startScore;
        double endScore;
        if (StringUtils.isBlank(level)) {
            startScore = ScoreLevelEnum.D.getScore();
            endScore = ScoreLevelEnum.A.getScore();
        } else {
            ScoreLevelEnum scoreLevelEnum = ScoreLevelEnum.valueOfDesc(level);
            switch (scoreLevelEnum) {
                case A:
                    startScore = ScoreLevelEnum.A.getScore();
                    endScore = Double.MAX_VALUE;
                    break;
                case B:
                    startScore = ScoreLevelEnum.B.getScore();
                    endScore = ScoreLevelEnum.A.getScore();
                    break;
                case C:
                    startScore = ScoreLevelEnum.C.getScore();
                    endScore = ScoreLevelEnum.B.getScore();
                    break;
                case D:
                    startScore = ScoreLevelEnum.D.getScore();
                    endScore = ScoreLevelEnum.C.getScore();
                    break;
                default:
                    startScore = ScoreLevelEnum.D.getScore();
                    endScore = ScoreLevelEnum.A.getScore();
            }
        }
        req.setStartScore(startScore);
        req.setEndScore(endScore);
        List<RiskReportQueryVo> riskReport = riskReportDAO.getRiskReport(req);
        riskReport.forEach(i -> i.setLevel(ScoreLevelEnum.desc(i.getScore())));
        return riskReport;
    }

    /**
     * 获取风险处置报告，通过id
     *
     * @param id id
     * @return RiskReport
     */
    public RiskReport getRiskReportById(long id) {
        return riskReportDAO.selectById(id);
    }

    /**
     * 新增风险处置报告
     *
     * @param report RiskReport
     */
    public boolean addRiskReport(RiskReport report) {
        final Long appraiseResultId = report.getAppraiseResultId();
        final Double score = report.getScore();
        if (appraiseResultId == null || report.getCreator() == null) {
            throw new BusinessException("评价结果id、创建人Id不能为空！");
        }
        if (score != null) {
            BigDecimal bg = BigDecimal.valueOf(score);
            report.setScore(bg.setScale(2, RoundingMode.HALF_UP).doubleValue());
        }
        if (report.getCreateTime() == null) {
            report.setCreateTime(new Date());
        }
        if (report.getStatus() == null) {
            report.setStatus(false);
        }
        final LambdaQueryWrapper<RiskReport> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(RiskReport::getAppraiseResultId, appraiseResultId);
        return saveOrUpdate(report, wrapper);
    }


    /**
     * 风险处置报告-处置任务
     *
     * @param req RiskReportDisposeDto
     */
    public int disposeTask(RiskReportDisposeDto req) {
        RiskReport param = new RiskReport();
        if (req.getId() == null || req.getDisposer() == null || StringUtils.isBlank(req.getDisposalContent())
                || StringUtils.isBlank(req.getDisposalOpinions())) {
            throw new BusinessException("id、处置人ID、处置内容、处置意见不能为空！");
        }
        param.setId(req.getId());
        param.setDisposer(req.getDisposer());
        param.setDisposalContent(req.getDisposalContent());
        param.setDisposalOpinions(req.getDisposalOpinions());
        param.setStatus(true);
        param.setUpdateTime(new Date());
        return riskReportDAO.updateById(param);
    }

    /**
     * 报告详情
     *
     * @param id id
     * @return row
     */
    public RiskReportDetailVo riskReportDetail(Long id) {
        RiskReportDetailVo vo = new RiskReportDetailVo();
        // 获取评价结果信息
        RiskReport riskReport = getRiskReportById(id);
        if (riskReport == null) {
            return null;
        }
        Long appraiseResultId = riskReport.getAppraiseResultId();
        vo.setSystemNo(riskReport.getSystemNo());
        vo.setSystemName(riskReport.getSystemName());
        vo.setMachineNo(riskReport.getMachineNo());
        vo.setScore(riskReport.getScore());
        vo.setLevel(ScoreLevelEnum.desc(vo.getScore()));
        vo.setCreateTime(riskReport.getCreateTime());
        // 各分析场景得分
        List<RiskReportDetailVo.SceneScore> sceneScores = new ArrayList<>();
        LambdaQueryWrapper<AppraiseSceneResult> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AppraiseSceneResult::getResultId, appraiseResultId);
        List<AppraiseSceneResult> list = appraiseSceneResultDAO.selectList(wrapper);
        List<Long> riskIds = new ArrayList<>();
        //扣分
        double totalDeductScore = SUM_SCORE - riskReport.getScore();
        for (AppraiseSceneResult p : list) {
            RiskReportDetailVo.SceneScore sceneScore = new RiskReportDetailVo.SceneScore();
            // 分析场景、得分
            String sceneName = p.getSceneName();
            Double score = p.getScore();
            Double deductScore = totalDeductScore * p.getRatio();
            // 详情
            List<AppraiseSceneResultDetail> detailList = appraiseSceneResultDetailService.listBySceneResultId(p.getId());
            List<RiskReportDetailVo.Risk> risks = new ArrayList<>();
            for (AppraiseSceneResultDetail detail : detailList) {
                RiskReportDetailVo.Risk risk = new RiskReportDetailVo.Risk();
                // 风险id、风险名称、权重
                Long riskId = detail.getRiskId();
                String riskName = detail.getRiskName();
                Double ratio = detail.getRatio();
                riskIds.add(riskId);
                risk.setRiskId(riskId);
                risk.setRiskName(riskName);
                risk.setRatio(ratio);
                BigDecimal bg = BigDecimal.valueOf(deductScore * ratio);
                risk.setScore(-bg.setScale(2, RoundingMode.HALF_UP).doubleValue());
                risks.add(risk);
            }
            sceneScore.setSceneName(sceneName);
            sceneScore.setScore(score);
            sceneScore.setRisks(risks);
            sceneScores.add(sceneScore);
        }
        // 风险处置策略、风险巡检项
        List<RiskPolicy> policies = riskPolicyService.getRiskPolicyByIds(riskIds);
        List<RiskInspection> inspections = riskInspectionService.getRiskInspectionBySystemNo(riskReport.getSystemNo());
        LinkedHashMap<String, List<RiskInspection>> map = new LinkedHashMap<>();
        for (RiskInspection dto : inspections) {
            String key = dto.getEquipmentCode();
            if (map.containsKey(key)) {
                map.get(key).add(dto);
            } else {
                List<RiskInspection> riskInspections = new ArrayList<>();
                riskInspections.add(dto);
                map.put(key, riskInspections);
            }
        }

        vo.setSceneScores(sceneScores);
        vo.setRiskPolicies(policies);
        vo.setInspections(map);
        return vo;
    }


    /**
     * 删除风险处置报告
     *
     * @param ids list
     */
    public int deleteRiskReport(List<Long> ids) {
        return riskReportDAO.deleteBatchIds(ids);
    }

    /**
     * 统计风险报告数据
     *
     * @return
     */
    public RiskReportStatisticsDto getRiskReportStatistics() {
        LambdaQueryChainWrapper<RiskReport> lambdaQueryWrapper = new LambdaQueryChainWrapper<>(riskReportDAO);
        List<RiskReport> list = lambdaQueryWrapper.in(RiskReport::getStatus, 1, 0)
                .le(RiskReport::getScore, ScoreLevelEnum.A.getScore())
                .list();
        Long handledCount = list.stream().filter(Objects::nonNull).filter(RiskReport::getStatus).count();
        Long notHandledCount = list.stream().filter(Objects::nonNull).filter(i -> !i.getStatus()).count();
        return RiskReportStatisticsDto.builder().handledCount(handledCount).notHandledCount(notHandledCount).build();
    }
}
